package com.fzy.common.util;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * CSV工具类
 *
 * @author 冯赵杨
 * @create 2018/8/16
 */
public class CsvUtil {
    private CsvUtil() {
    }

    private static final Logger logger = LoggerFactory.getLogger(CsvUtil.class);

    /**
     * 定义 限制条件
     */
    private static final String MS_CSV_CONTENT_TYPE = "Content-Type: text/csv";


    public enum ResultCode {
        SUCCESS, NOT_VALID, DATA_ERROR, EXCEPTION
    }

    public static class LimitDefine {

        /**
         * 文件最大大小 默认10M
         */
        private static Long MAX_SIZE = 10 * 1024 * 1024L;

        /**
         * 文件类型
         */
        private static String FILE_TYPE = "csv";

        /**
         * 最大行数限制100000
         */
        private static int MAX_LINES = 100000;

    }

    /**
     * 导入文件
     *
     * @param file
     * @return
     * @author 冯赵杨
     * @create 2018/8/16
     */
    public static CsvResult importCsv(MultipartFile file) {

        CsvResult csvResult = new CsvResult();
        try {
            // 简单校验
            csvResult = simpleCheck(file);
            if (simpleCheck(file).isSuccess()) {

                CsvReader csvReader = new CsvReader(file.getInputStream(), Charset.forName("UTF-8"));

                List<String> headerList = null;
                List<List<String>> dataList = new ArrayList<>();

                //对读取的行数进行限制计数
                int num = 0;

                while (csvReader.readRecord()) {
                    //行数计数
                    num++;
                    //逐行读入数据
                    String[] arrays = csvReader.getValues();

                    if (arrays != null && arrays.length > 0) {
                        //保存表头
                        if (csvReader.getCurrentRecord() == 0) {
                            headerList = Arrays.asList(arrays);
                        } else {
                            //保存数据
                            List<String> data = new ArrayList<>();
                            for (String item : arrays) {
                                data.add(item.trim());
                            }
                            dataList.add(data);
                        }

                    }

                    //行数超过限制
                    if (num > LimitDefine.MAX_LINES) {
                        csvResult.addMsg("上传的文件超过限制行数！");
                        csvResult.setResultCode(ResultCode.NOT_VALID);
                        return csvResult;
                    }
                }
                csvReader.close();
                csvResult.setResultCode(ResultCode.SUCCESS);
                csvResult.setHeadList(headerList);
                csvResult.setDataList(dataList);
                csvResult.setTotalCount(dataList.size());

            }

        } catch (Exception e) {
            e.printStackTrace();
            csvResult.setResultCode(ResultCode.EXCEPTION);
        }

        return csvResult;

    }

    /**
     * 导出文件
     *
     * @param headArray
     * @param dataList
     * @param fileName
     * @return
     * @author 冯赵杨
     * @create 2018/8/16
     */
    public static void exportCsv(String[] headArray, List<String[]> dataList, String fileName,
                                 HttpServletResponse response) {
        OutputStream os;
        CsvResult csvResult = new CsvResult();
        try {
            if (StringUtil.isEmpty(fileName)) {
                fileName = UUID.randomUUID().toString();
            }
            String exportFileName = new String(fileName.getBytes("gbk"), "ISO8859-1");
            String exportName = exportFileName.concat(".").concat(LimitDefine.FILE_TYPE);
            response.setContentType(MS_CSV_CONTENT_TYPE);
            response.setHeader("Content-disposition", "attachment;filename=" + exportName);
            response.setHeader("Cache-Control", "must-revalidate,post-check=0,pre-check=0");
            response.setHeader("Expires", "0");
            response.setHeader("Pragma", "public");
            os = response.getOutputStream();
            os.write("sep=,\r\n".getBytes());
            CsvWriter wr = new CsvWriter(os, ',', Charset.forName("GBK"));
            // 写入表头的数据
            if (null != headArray && headArray.length > 0) {
                wr.writeRecord(headArray);
            }
            // 写入内容数据
            if (StringUtil.isNotNull(dataList)) {
                for (String[] data : dataList) {
                    if (null != data && data.length > 0) {
                        wr.writeRecord(data);
                    }
                }
            }
            wr.close();
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
            csvResult.setResultCode(ResultCode.EXCEPTION);
        }
    }

    /**
     * CSV操作结果
     *
     * @author 冯赵杨
     * @create 2018/8/16
     */
    static public class CsvResult {

        /**
         * 总行数
         */
        public int totalCount = 0;

        /**
         * 标题
         */
        List<String> headList = new ArrayList<>();

        /**
         * 数据
         */
        List<List<String>> dataList = new ArrayList<>();

        /**
         * 结果码
         */
        private ResultCode resultCode = ResultCode.SUCCESS;

        /**
         * 返回结果码
         */
        public ResultCode getResultCode() {
            return resultCode;
        }

        /**
         * 设置结果码
         */
        public void setResultCode(ResultCode resultCode) {
            this.resultCode = resultCode;
        }

        /**
         * 结果信息
         */
        private List<String> messageList = new ArrayList<>();

        public List<String> getMessageList() {
            return messageList;
        }

        public void setMessageList(List<String> messageList) {
            this.messageList = messageList;
        }

        /**
         * 新增信息
         */
        public void addMsg(String msg) {
            messageList.add(msg);
        }

        /**
         * 是否成功
         */
        public boolean isSuccess() {
            if (resultCode == ResultCode.SUCCESS) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }

        /**
         * 是否验证通过
         */
        public boolean isNotValid() {
            if (resultCode == ResultCode.NOT_VALID) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }

        /**
         * 获取处理的概要消息
         */
        public String getSummaryMsg() {
            if (totalCount == 0) {
                return "没有可处理的记录!";
            }
            return MessageFormat.format("共上传{0}行数据!", totalCount);
        }

        public int getTotalCount() {
            return totalCount;
        }

        public List<List<String>> getDataList() {
            return dataList;
        }

        public void setTotalCount(int totalCount) {
            this.totalCount = totalCount;
        }

        public void setDataList(List<List<String>> dataList) {
            this.dataList = dataList;
        }

        public List<String> getHeadList() {
            return headList;
        }

        public void setHeadList(List<String> headList) {
            this.headList = headList;
        }

        @Override
        public String toString() {
            return "CsvResult [dataList=" + dataList + ", headList=" + headList
                    + ", messageList=" + messageList + ", resultCode=" + resultCode
                    + ", totalCount=" + totalCount + "]";
        }
    }

    /**
     * 上传文件检查
     *
     * @param file
     * @return
     * @author 冯赵杨
     * @create 2018/8/16
     */
    private static CsvResult simpleCheck(MultipartFile file) {

        // 返回对象
        CsvResult result = new CsvResult();

        // 判断上传文件是否为空
        if (file == null || file.getName() == null) {
            logger.error("upload file is empty!");

            result.addMsg("上传的文件为空!");
            result.setResultCode(ResultCode.NOT_VALID);
            return result;
        }
        // 判断上传文件的大小是否为空
        if (file.getSize() == 0) {
            logger.error("upload file size is empty!");

            result.addMsg("上传的文件大小为空!");
            result.setResultCode(ResultCode.NOT_VALID);
            return result;
        }
        // 判断上传文件的大小是否超出限制
        if (file.getSize() > LimitDefine.MAX_SIZE) {
            logger.error("upload file size overstep max.:" + LimitDefine.MAX_SIZE / (1024 * 1024)
                    + "M!");

            result.addMsg(MessageFormat.format("上传的文件大小超过最大值：{0}M!", LimitDefine.MAX_SIZE
                    / (1024 * 1024)));
            result.setResultCode(ResultCode.NOT_VALID);
            return result;
        }
        // 判断上传文件是否为允许处理的类型
        String extension = getExtension(file.getOriginalFilename());
        if (!StringUtil.equalsIgnoreCase(extension, LimitDefine.FILE_TYPE)) {
            logger.error("file format is error,please upload .csv CSV file!");
            result.addMsg(MessageFormat.format("文件格式错误，请上传{0}扩展名的文件", LimitDefine.FILE_TYPE));
            result.setResultCode(ResultCode.NOT_VALID);
            return result;
        }

        return result;
    }

    /**
     * 获取扩展名
     *
     * @param fileName
     * @return
     * @author 冯赵杨
     * @create 2018/8/16
     */
    private static String getExtension(String fileName) {
        int pos = fileName.lastIndexOf(".");
        return fileName.substring(pos + 1);
    }
}
